/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package semant.second_pass;

import semant.Env;
import symbol.ClassInfo;
import symbol.Symbol;
import syntaxtree.ClassDecl;
import syntaxtree.ClassDeclExtends;
import syntaxtree.Program;
import syntaxtree.Type;
import syntaxtree.VisitorAdapter;
import util.List;

/**
 *
 * @author Thiago
 */
class InheritanceBuilder extends VisitorAdapter {

    private Env env;

    Program programa;

    InheritanceBuilder(Env e, Program p)
    {
        env = e;
        programa = p;
    }

    static void secondPass(Env e, Program p) {

        InheritanceBuilder h = new InheritanceBuilder(e,p);

        for(List<ClassDecl> classes = p.classList;classes!=null;classes = classes.tail)
        {
            classes.head.accept(h);
        }
    }

     public void visit(ClassDeclExtends node)
     {
         ClassInfo atual = env.classes.get(Symbol.symbol(node.name.s));

         ClassInfo infoPai = env.classes.get(Symbol.symbol(node.superClass.s));

        if(infoPai==null)
        {
            env.err.Error(node,new Object[]{"Classe pai não foi declarada.","Simbolo: "+node.superClass.toString()});
        }
        else{
            if(atual.base==null){
                if(Type.isCompatible(atual,infoPai))
                {
                    atual.base = new ClassInfo(null);
                    env.err.Error(node.name,new Object[]{"Tentativa de herança ciclica.",
                                        "A classe \'"+ node.superClass.s + "\' já extende a classe \'"+node.name.s + "\'"});
                }
                else
                {

                    atual.base = infoPai;
                    for(List<ClassDecl> classes = programa.classList;classes!=null;classes = classes.tail)
                    {
                        if(classes.head.name.toString().equalsIgnoreCase(infoPai.name.toString()))
                        {
                            InheritanceBuilder h = new InheritanceBuilder(env,programa);
                            classes.head.accept(h);
                        }
                    }
                    atual.setBase(infoPai);
                }
            }
        }         
     }


}
